import java.nio.ByteBuffer;

public class HistogramAnalyzer {

	final int num_colour_bins = 16;
	final int num_grayscale_bins = 256;

	double[][][] hist_arr = new double[num_colour_bins][num_colour_bins][num_colour_bins];
	double[][][] prev_hist_arr = new double[num_colour_bins][num_colour_bins][num_colour_bins];

	double[] Y_hist = new double[num_grayscale_bins];
	double[] Y_prev_hist = new double[num_grayscale_bins];

	double SAD = 0;

	int img_width;
	int img_height;

	HistogramAnalyzer(int width, int height) {
		img_width = width;
		img_height = height;
	}

	double getScore(ByteBuffer buffer) {
		
		//System.out.println("Calculating Histogram difference...");
        initArray(hist_arr);
        //initArrayY(Y_hist);

        int ind = 0;
        for(int y = 0; y < img_height; y++) {
			for(int x = 0; x < img_width; x++) 	{
				int r = (int) (buffer.get(ind) & 0xff);
				int g = (int) (buffer.get(ind+img_height*img_width) & 0xff);
		        int b = (int) (buffer.get(ind+img_height*img_width*2) & 0xff);

		        formulateHistogram(r,g,b);
				//formulateYHistogram(r,g,b);
				
				ind ++;
			}
        }

		return calculateHistogramDifference();
	}

	private void initArray(double arr[][][]) {
		for (int y = 0; y < num_colour_bins; y++) {
			for (int x = 0; x < num_colour_bins; x++) {
				for (int z = 0; z < num_colour_bins; z++) {
					arr[y][x][z] = 0.0;
				}
			}
		}
	}

	@SuppressWarnings("unused")
	private void initArrayY(double arr[]) {
		for (int y = 0; y < num_grayscale_bins; y++) {
			arr[y] = 0.0;
		}
	}

	public void formulateHistogram(int r, int g, int b) {
		int stepsize = 16;
		int div_r = 0, div_g = 0, div_b = 0;

		div_r = (int) (r / stepsize);
		div_g = (int) (g / stepsize);
		div_b = (int) (b / stepsize);

		hist_arr[div_r][div_g][div_b] += 1;

	}

	@SuppressWarnings("unused")
	private void formulateYHistogram(int R, int G, int B) {
		double Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16;
		if (Y < 0.0) {
			Y = 0.0;
		}
		if (Y > 255.0) {
			Y = 255.0;
		}
		int YY = (int) Math.round(Y);
		// System.out.println("Y"+Y+" "+YY);
		Y_hist[YY] += 1;
		// System.out.println("YY["+YY+"]="+Y_hist[YY]);

	}

	public double calculateHistogramDifferenceY() {
		double diff = 0.0;
		for (int r = 0; r < 256; r++) {

			double prev = Y_prev_hist[r];
			double cur = Y_hist[r];

			diff += Math.abs(prev - cur);
			Y_prev_hist[r] = Y_hist[r];

		}

		return diff;
	}

	public double calculateHistogramDifference() {
		double diff = 0.0;

		for (int r = 0; r < num_colour_bins; r++) {
			for (int g = 0; g < num_colour_bins; g++) {
				for (int b = 0; b < num_colour_bins; b++) {
					double prev = prev_hist_arr[r][g][b];
					double cur = hist_arr[r][g][b];
					// System.out.println(diff);
					diff += Math.abs(prev - cur);
					prev_hist_arr[r][g][b] = hist_arr[r][g][b];
					// if(hist_arr[r][g][b] != 0)
					// System.out.print( hist_arr[r][g][b] + " ");

				}
			}
		}

		return diff;
	}

}
